package com.aegis.gateway.utils;

import cn.dev33.satoken.reactor.context.SaReactorSyncHolder;
import cn.dev33.satoken.stp.StpUtil;
import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.core.util.URLUtil;
import cn.hutool.json.JSONUtil;
import com.aegis.common.exception.AuthorizationException;
import com.aegis.common.web.BaseResponseEnum;
import com.aegis.sdk.signature.model.SignatureParams;
import com.aegis.sdk.signature.utils.SignatureUtil;
import com.aegis.spring.config.AegisAppProperties;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.server.reactive.ServerHttpRequest;
import org.springframework.stereotype.Component;
import org.springframework.web.server.ServerWebExchange;

import java.io.UnsupportedEncodingException;
import java.net.URLDecoder;
import java.nio.charset.Charset;
import java.util.List;
import java.util.Map;
import java.util.Optional;

/**
 * @Author renogo
 * 
 * @Version 1.0
 * @Descritube 获取用户登录信息的工具
 */
@Component
@Slf4j
public class AuthUtil {

    private static AegisAppProperties aegisAppProperties;

    private final static ThreadLocal<ServerWebExchange> serverWebExchangeThreadLocal = new ThreadLocal<>();

    @Autowired
    public AuthUtil(AegisAppProperties aegisAppProperties) {
        this.aegisAppProperties = aegisAppProperties;
    }


    /**
     * 获取当前登录的用户的权限
     *
     * @return
     */
    public static List<String> getPermission() {
        return StpUtil.getPermissionList();
    }

    /**
     * 获取某个用户的权限
     *
     * @param userId
     * @return
     */
    public static List<String> getPermission(String userId) {
        return StpUtil.getPermissionList(userId);
    }


    /**
     * 获取当前用户的角色
     *
     * @return
     */
    public static List<String> getRoles() {
        return StpUtil.getRoleList();
    }

    /**
     * 获取当前用户的角色
     *
     * @return
     */
    public static List<String> getRoles(String userId) {
        return StpUtil.getRoleList(userId);
    }


    /**
     * 获取当前登录的用户id
     *
     * @return
     */
    public static String getUserId() {
        return (String) StpUtil.getLoginId();
    }

    /**
     * 获取当前登录的用户token
     *
     * @return
     */
    public static String getToken() {
        return StpUtil.getTokenValue();
    }


    /**
     * 获取当前请求头的 appId
     *
     * @return appId 值，如果请求头中没有则返回 null
     */
    public static String getAppId() {
        return getHeader(aegisAppProperties.getHeaderNameAppId());
    }

    /**
     * @return
     */
    public static String getNonce() {
        return getHeader(aegisAppProperties.getHeaderNameNonce());
    }

    /**
     * @return
     */
    public static String getTimestamp() {
        return getHeader(aegisAppProperties.getHeaderNameTimestamp());
    }


    /**
     * @return
     */
    public static String getSignature() {
        return getHeader(aegisAppProperties.getHeaderSignature());
    }

    /**
     *
     */
    public static void checkSignature(String secret) {
        checkSignature(secret, "");
    }

    /**
     *
     */
    public static void checkSignature(String secret, String body) {
        ServerWebExchange context = getContext();
        ServerHttpRequest request = context.getRequest();
        // 获取查询参数
        Map<String, String> queryParams = request.getQueryParams().toSingleValueMap();
        SignatureParams.Builder builder = SignatureParams
                .builder()
                .body(body)
                .timestamp(getTimestamp())
                .nonce(getNonce())
                .appId(getAppId())
                .queryMap(queryParams);
        checkSignature(secret, builder.build());
    }

    public static void checkSignature(String secret, SignatureParams signatureParams) {
        if (StrUtil.isEmpty(signatureParams.getAppId())) {
            throw new AuthorizationException(BaseResponseEnum.UNAUTHORIZED, "appId不能为空");
        }
        if (StrUtil.isEmpty(signatureParams.getNonce())) {
            throw new AuthorizationException(BaseResponseEnum.UNAUTHORIZED, "nonce不能为空");
        }
        if (StrUtil.isEmpty(signatureParams.getTimestamp())) {
            throw new AuthorizationException(BaseResponseEnum.UNAUTHORIZED, "timestamp不能为空");
        }
        if (StrUtil.isEmpty(getSignature())) {
            throw new AuthorizationException(BaseResponseEnum.UNAUTHORIZED, "signature不能为空");
        }
        if (Long.parseLong(signatureParams.getTimestamp()) + aegisAppProperties.getExpire() <
                System.currentTimeMillis()) {
            throw new AuthorizationException(BaseResponseEnum.UNAUTHORIZED, "签名已过期");
        }
        String signature = SignatureUtil.generateSignature(signatureParams, secret);
        if (!signature.equals(getSignature())) {
            log.info("签名内容：{}", JSONUtil.toJsonStr(signatureParams));
            log.info("密钥：{}", secret);
            log.info("签名结果: {}", signature);
            throw new AuthorizationException(BaseResponseEnum.UNAUTHORIZED, "签名错误");
        }
    }


    public static String getHeader(String key) {
        ServerWebExchange context = Optional.ofNullable(getContext()).orElse(SaReactorSyncHolder.getContext());
        if (context == null) {
            throw new RuntimeException("找不到上下文");
        }
        ServerHttpRequest request = context.getRequest();
        List<String> headers = request.getHeaders().get(key);
        if (CollectionUtil.isEmpty(headers)) {
            return null;
        }
        return headers.get(0);
    }


    public static void setContext(ServerWebExchange serverWebExchange) {
        serverWebExchangeThreadLocal.set(serverWebExchange);
    }


    public static ServerWebExchange getContext() {
        return serverWebExchangeThreadLocal.get();
    }

    public static void clearContext() {
        serverWebExchangeThreadLocal.remove();
    }

}
